/*
 * Copyright 2009 by Konstantin Bulenkov
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.bulenkov.crawler.filter;

import com.bulenkov.crawler.CURL;

/**
 * @author Konstantin Bulenkov
 */
public class FilterFactory {
  private FilterFactory() {}
  public static Filter ALLOW_ALL = new Filter() {
    public boolean accept(CURL link) {
      return true;
    }
  };

  public static Filter DISALLOW_ALL = new Filter() {
    public boolean accept(CURL link) {
      return false;
    }
  };

  public static FilterFactory getInstance() {
    return FilterFactoryHolder.INSTANCE;
  }

  public Filter and(final Filter... filters) {
    return new Filter() {
      public boolean accept(CURL link) {
        for (Filter filter : filters) {
          if (!filter.accept(link)) return false;
        }
        return true;
      }

      @Override
      public String toString() {
        if (filters.length == 0) return "";
        if (filters.length == 1) return filters[0].toString();
        StringBuilder s = new StringBuilder("(");
        for (Filter filter : filters) {
          s.append("(").append(filter).append(") AND ");
        }
        s.delete(s.length() - 5, s.length()).append(")");
        return s.toString();
      }
    };
  }

  public Filter or(final Filter... filters) {
    return new Filter() {
      public boolean accept(CURL link) {
        for (Filter filter : filters) {
          if (filter.accept(link)) return true;
        }
        return false;
      }

      @Override
      public String toString() {
        if (filters.length == 0) return "";
        if (filters.length == 1) return filters[0].toString();
        StringBuilder s = new StringBuilder("(");
        for (Filter filter : filters) {
          s.append("(").append(filter).append(") OR ");
        }
        s.delete(s.length() - 4, s.length()).append(")");
        return s.toString();
      }
    };
  }

  public Filter not(final Filter filter) {
    return new Filter() {
      public boolean accept(CURL link) {
        return ! filter.accept(link);
      }

      @Override
      public String toString() {
        return "NOT " + filter;
      }
    };
  }

  public Filter regex(final String regex) {
    return new RegexFilter(regex);
  }

  public Filter contains(final String needle) {
    return new Filter() {
      public boolean accept(CURL link) {
        return link.url().contains(needle);
      }

      @Override
      public String toString() {
        return "CONTAINS: `" + needle + "`";
      }
    };
  }

  public Filter startsWith(final String start) {
    return new Filter() {
      public boolean accept(CURL link) {
        return link.url().startsWith(start);
      }

      @Override
      public String toString() {
        return "STARTS WITH: `" + start + "`";
      }
    };
  }

  public Filter endsWith(final String end) {
    return new Filter() {
      public boolean accept(CURL link) {
        return link.url().endsWith(end);
      }

      @Override
      public String toString() {
        return "ENDS WITH: `" + end + "`";
      }
    };
  }

  private static class FilterFactoryHolder {
    private static final FilterFactory INSTANCE = new FilterFactory();
  }
}
